home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-01-31 | 9.0 KB | 302 lines | [TEXT/MPS ] |
- unit UHeapHandler;
- (* Written by Richard Clark (AppleLink, Delphi, GEnie, MCI, MouseHole: RDCLARK *)
- (* Internet: rdclark@apple.com or rdclark@applelink.apple.com) *)
- (* Copyright (c) 1989 by Apple Computer, Inc. All Rights Reserved *)
-
- interface
- {$S Main}
-
- uses
- Types, QuickDraw, Menus, Memory, Windows, Dialogs, Fonts, Packages, ToolUtils,
- UGlobals;
-
- const
- kDontShowSelection = FALSE;
- kDoShowSelection = TRUE;
-
- kLeaveDirtyFlags = FALSE;
- kClearDirtyFlags = TRUE;
-
- procedure ZeroHeapInfo (var whichHeap: HeapInfo);
-
- procedure CopyHeapInfo (fromHeap: HeapInfo; var toHeap: HeapInfo);
-
- procedure UpdateHeapInfo (var whichHeap: HeapInfo; keepDirtyBlocks: Boolean);
-
- procedure DrawHeap (whichHeap: HeapInfo; showSelection: Boolean);
- procedure DrawBlock (blockNum: integer; whichHeap: HeapInfo; showSelection: Boolean);
-
- implementation
-
- procedure BlockToRect (blkNum: INTEGER; var blockRect: Rect; whichHeap: HeapInfo);
- (* Given the number of a "heap info" array element, calculate the rectangle it occupies on *)
- (* the screen. (The "user item" rectangle containing this one comes from the HeapInfo record) *)
- var
- relStart: LONGINT;
-
- begin
- with whichHeap.blocks[blkNum] do
- begin
- relStart := blkStart - ORD(MyDemoZone) - HeapBias;
- blockRect := whichHeap.heapRect;
- InsetRect(blockRect, 1, 1);
- blockRect.bottom := whichHeap.heapRect.bottom - relStart div bytesPerPixel;
- blockRect.top := whichHeap.heapRect.bottom - (relStart + blkSize) div bytesPerPixel;
- if (blockRect.top <= whichHeap.heapRect.top) then
- blockRect.top := whichHeap.heapRect.top + 1;
- end;
- end; (* BlockToRect *)
-
-
- procedure InvalBlock (blockNum: integer; whichHeap: HeapInfo);
- (* Invalidate the specified memory block on the screen. This is not presently used, as we forcibly *)
- (* redraw the entire heap every time something is changed.) *)
- var
- blockRect: Rect;
-
- begin
- BlockToRect(blockNum, blockRect, whichHeap);
- InvalRect(blockRect);
- end; (* InvalBlock *)
-
-
- procedure ZeroHeapInfo (var whichHeap: HeapInfo);
- (* Initialize a Heap Info record *)
- var
- blkNum: integer;
-
- begin
- with whichHeap do
- begin
- numBlocks := 0;
- blocksUsed := 0;
- selectedBlock := 0;
- (* we'll initialize the rest of the fields later *)
- for blkNum := 1 to MyArraySize do
- with blocks[blkNum] do
- begin
- blkType := blkFree;
- blkStart := 0;
- blkSize := 0;
- blkOldStart := 0;
- blkDirty := FALSE;
- end;
- end;
- end; (* ZeroHeapInfo *)
-
-
- procedure CopyHeapInfo (fromHeap: HeapInfo; var toHeap: HeapInfo);
- (* Copy the information from one heap to another, preserving the bounds rectangle and the old base addresses *)
- var
- count: INTEGER;
- isDirty: Boolean;
-
- begin
- toHeap.numBlocks := fromHeap.numBlocks;
- toHeap.blocksUsed := fromHeap.blocksUsed;
- toHeap.selectedBlock := fromHeap.selectedBlock;
- toHeap.maxFreeBytes := fromHeap.maxFreeBytes;
- toHeap.maxBlocks := fromHeap.maxBlocks;
- toHeap.maxAvailBytes := fromHeap.maxAvailBytes;
- toHeap.maxAfterCompact := fromHeap.maxAfterCompact;
- toHeap.maxAfterPurge := fromHeap.maxAfterPurge;
- (* toHeap.heapRect is not copied *)
- for count := 1 to MyArraySize do
- begin
- (* Mark a block dirty if it was dirty or the type changed *)
- isDirty := (fromHeap.blocks[count].blkDirty) or (toHeap.blocks[count].blkType <> fromHeap.blocks[count].blkType);
- toHeap.blocks[count].blkDirty := isDirty;
- toHeap.blocks[count].blkType := fromHeap.blocks[count].blkType;
- toHeap.blocks[count].blkSource := fromHeap.blocks[count].blkSource;
- toHeap.blocks[count].blkStart := fromHeap.blocks[count].blkStart;
- (* toHeap.blocks[count].blkOldStart is not copied, so we can detect which blocks have moved *)
- toHeap.blocks[count].blkSize := fromHeap.blocks[count].blkSize;
- toHeap.blocks[count].blkSequence := fromHeap.blocks[count].blkSequence;
- toHeap.blocks[count].blkLocked := fromHeap.blocks[count].blkLocked;
- toHeap.blocks[count].blkPurgeable := fromHeap.blocks[count].blkPurgeable;
- end;
- end; (* MoveHeapInfo *)
-
-
- procedure UpdateHeapInfo;
- (* This scans the heap infor record, updating the statistics contained therein *)
- var
- blkNum: integer;
- newStart: LONGINT;
- oldPort: GrafPtr;
-
- begin
- (* Update the current starting addresses of each of the relocatable blocks *)
- for blkNum := 1 to MyArraySize do
- with whichHeap.blocks[blkNum] do
- begin
- if (blkType = blkHandle) then
- begin
- newStart := ORD(StripAddress(Handle(blkSource)^));
- if newStart = 0 then (* This code added to "Free" a relocatable block if it is purged *)
- blkType := blkFree;
- end
- else if (blkType = blkPointer) then
- newStart := ORD(blkSource)
- else if (blkType = blkFree) then
- newStart := 0;
- if (blkStart <> newStart) or blkDirty then
- begin
- GetPort(oldPort);
- SetPort(MemoryDialog);
- (* invalidate the old rectangle *)
- if (blkStart = 0) or (blkStart = newStart) then
- blkStart := blkOldStart; (* Use the old address, which should still be valid *)
- (* InvalBlock(blkNum, whichHeap); *)
- blkOldStart := blkStart;
- blkStart := newStart;
- {$IFC FALSE}
- if (blkType = blkHandle) then (* Invalidate the new rectangle *)
- InvalBlock(blkNum, whichHeap);
- {$ENDC}
- SetPort(oldPort);
- blkDirty := blkDirty and not keepDirtyBlocks;
- end;
- end;
-
- SetZone(MyDemoZone);
- with whichHeap do
- begin
- (* Update the heap statistics *)
- maxFreeBytes := FreeMem;
- maxBlocks := maxFreeBytes div 1024;
- if system.EnhancedROMs then
- begin
- PurgeSpace(maxAvailBytes, maxAfterPurge);
- maxAfterCompact := MaxBlock;
- end
- else
- begin
- maxAvailBytes := -1;
- maxAfterCompact := -1;
- maxAfterPurge := -1;
- end
- end;
- SetZone(MyAppZone);
-
- end; (* UpdateHeapInfo *)
-
-
- procedure DrawBlock (blockNum: integer; whichHeap: HeapInfo; showSelection: Boolean);
- (* Given an array index, draw the specified block on the screen *)
- var
- blockRect: Rect;
- blockPat: Pattern;
- bnString: Str255;
- oldFace: Style;
- oldFont, oldSize: INTEGER;
- labelString, aString: Str255;
- whiteOutRect: Rect;
-
- begin
- blockToRect(blockNum, blockRect, whichHeap);
- with whichHeap.blocks[blockNum] do
- if blkType = blkHandle then
- begin
- GetIndPattern(blockPat, sysPatListID, 22); { 25% Gray }
- ForeColor(greenColor);
- end
- else if blkType = blkPointer then
- begin
- GetIndPattern(blockPat, sysPatListID, 28); { Diagonal Lines }
- ForeColor(redColor);
- end
- else if blkType = blkMaster then
- begin
- GetIndPattern(blockPat, sysPatListID, 33); { Up Arrows }
- ForeColor(magentaColor);
- end;
- FillRect(blockRect, blockPat);
- FrameRect(blockRect);
-
- (* Now, draw the block's assigned number *)
- oldFont := thePort^.txFont;
- oldSize := thePort^.txSize;
- oldface := thePort^.txFace;
-
- ForeColor(blackColor);
- PenMode(patCopy);
- MoveTo(blockRect.left + 2, blockRect.bottom - 3);
- TextFont(geneva);
- TextFace([bold]);
- TextSize(9);
- NumToString(whichHeap.blocks[blockNum].blkSequence, bnString);
- DrawString(bnString);
- TextFace([]);
- labelString := '';
- if whichHeap.blocks[blockNum].blkLocked = TRUE then
- begin
- GetIndString(aString, 1000, 1);
- Insert(aString, labelString, length(labelString) + 1);
- end;
- if whichHeap.blocks[blockNum].blkPurgeable = TRUE then
- begin
- GetIndString(aString, 1000, 2);
- Insert(aString, labelString, length(labelString) + 1);
- end;
- if (labelString <> '') then
- begin
- SetRect(whiteOutRect, 0, -9, StringWidth(labelString) + 1, 2);
- with thePort^.pnLoc do
- OffsetRect(whiteOutRect, h, v);
- EraseRect(whiteOutRect);
- DrawString(labelString);
- end;
-
- TextFont(oldFont);
- TextSize(oldSize);
- TextFace(oldFace);
-
- if (blockNum <> 0) and (whichHeap.selectedBlock = blockNum) and showSelection then
- begin
- InsetRect(blockRect, 1, 1);
- InvertRect(blockRect);
- end;
- end; (* DrawBlock *)
-
-
- procedure DrawHeap (whichHeap: HeapInfo; showSelection: Boolean);
- (* This draws the contents of the specified heap zone on the screen *)
-
- var
- v, dv: integer;
- count: integer;
- blkNum: integer;
-
- begin
- (* Frame the display area *)
- PenPat(black);
- PenSize(1, 1);
- EraseRect(whichHeap.heapRect); (* erase before framing, since EraseRect will destroy the frame also *)
- FrameRect(whichHeap.heapRect);
-
- (* draw the cross-bars *)
- PenPat(gray);
- with whichHeap.heapRect do
- begin
- dv := (bottom - top) div MyHeapSize;
- v := top;
- for count := 1 to MyHeapSize - 1 do
- begin
- v := v + dv;
- MoveTo(left + 1, v);
- LineTo(right - 2, v);
- end;
- end;
- PenPat(black);
-
- (* Now, draw each of the blocks in the heap *)
- if whichHeap.blocksUsed > 0 then
- for blkNum := 1 to MyArraySize do
- with whichHeap.blocks[blkNum] do
- if (blkType <> blkFree) then
- DrawBlock(blkNum, whichHeap, showSelection);
- ForeColor(blackColor);
- end; (* DrawHeap *)
-
- end.